module spi_driver #(parameter   SYS_CLOCK   = 50_000_000    ,
                                SPI_RATE    = 625_000       ,
                                CPOL        = 1'b0          ,//时钟极性
                                CPHA        = 1'b0          ,//时钟相位
                                DATA_LENTH  = 8
                                )(
    input               clk         ,
    input               rst_n       ,
    input               rw_flag     ,
    input       [7:0]   wr_data     ,
    output  reg [7:0]   rd_data     ,
    output              trans_done  ,
    //---------<spi>------------------------------------------------- 
    output    reg       sclk        ,
    output    reg       mosi        ,
    output              cs_n        ,
    input               miso
);

localparam  FRQ_DEVICE = SYS_CLOCK/SPI_RATE;//分频时钟系数

//scl计数器
reg		[$clog2(FRQ_DEVICE)-1:0]	cnt_scl	   ;//串行时钟计数器
wire			                    add_cnt_scl;
wire			                    end_cnt_scl;

//bit计数器
reg		[$clog2(DATA_LENTH)-1:0]	cnt_bit;
wire			                    add_cnt_bit;
wire			                    end_cnt_bit;

//---------<cnt_scl>------------------------------------------------- 

always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_scl <= 'd0;
    end 
    else if(add_cnt_scl)begin 
        if(end_cnt_scl)begin 
            cnt_scl <= 'd0;
        end
        else begin 
            cnt_scl <= cnt_scl + 1'b1;
        end 
    end
end 

assign add_cnt_scl = rw_flag;
assign end_cnt_scl = add_cnt_scl && cnt_scl == FRQ_DEVICE-1;

//---------<sclk>------------------------------------------------- 

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        sclk <= CPOL;
    end
    else if(rw_flag)begin
        if(cnt_scl < (FRQ_DEVICE)>>1)begin
            sclk <= CPHA ? ~CPOL : CPOL;
        end
        else begin
            sclk <= CPHA ? CPOL : ~CPOL;
        end
    end
    else begin
        sclk <= CPOL;
    end
end

//---------<cnt_bit>------------------------------------------------- 

always @(posedge clk or negedge rst_n)begin 
   if(!rst_n)begin
        cnt_bit <= 'd0;
    end 
    else if(add_cnt_bit)begin 
        if(end_cnt_bit)begin 
            cnt_bit <= 'd0;
        end
        else begin 
            cnt_bit <= cnt_bit + 1'b1;
        end 
    end
end 

assign add_cnt_bit = end_cnt_scl;
assign end_cnt_bit = add_cnt_bit && cnt_bit == DATA_LENTH-1;

//---------<cs_n>------------------------------------------------- 

assign cs_n = ~rw_flag;

//---------<mosi>------------------------------------------------- 

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        mosi <= 1'b0;
    end
    else if(rw_flag)begin
        mosi <= wr_data[7-cnt_bit];
    end
end

//---------<rd_data>------------------------------------------------- 

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        rd_data <= 'd0;
    end
    else if(rw_flag && cnt_scl == (FRQ_DEVICE >> 1) - 1)begin
        rd_data[7-cnt_bit] <= miso;
    end
end

assign trans_done = end_cnt_bit;

endmodule